package handler

import (
	// "context"
	// "fmt"
	"net/http"
	"time"

	"mall/service/wpgql/api/internal/graph/dataloader"
	"mall/service/wpgql/api/internal/graph/generated"
	"mall/service/wpgql/api/internal/graph/resolver"
	"mall/service/wpgql/api/internal/svc"

	// "github.com/99designs/gqlgen/graphql"
	"github.com/99designs/gqlgen/graphql/handler"
	"github.com/99designs/gqlgen/graphql/handler/extension"
	"github.com/99designs/gqlgen/graphql/handler/lru"
	"github.com/99designs/gqlgen/graphql/handler/transport"
	"github.com/gorilla/websocket"
	"github.com/zeromicro/go-zero/core/service"
)

// Defining the Graphql handler
func GraphqlHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	// make a data loader
	loader := dataloader.NewDataLoader(svcCtx)
	// NewExecutableSchema and Config are in the generated.go file
	// Resolver is in the resolver.go file
	// instantiate the gqlgen Graph Resolver
	// graphResolver := resolver.NewResolver(svcCtx)

	// create the query handler
	srv := handler.New(generated.NewExecutableSchema(generated.Config{
		Resolvers:  resolver.NewResolver(svcCtx),
		Directives: resolver.NewDirective(),
	}))
	srv.AddTransport(transport.Websocket{
		KeepAlivePingInterval: 10 * time.Second,
		Upgrader: websocket.Upgrader{
			CheckOrigin: func(r *http.Request) bool {
				return true
				// Check against your desired domains here
				// return r.Host == "localhost"
			},
			// ReadBufferSize:  1024,
			// WriteBufferSize: 1024,
		},
	})
	srv.AddTransport(transport.Options{})
	srv.AddTransport(transport.GET{})
	srv.AddTransport(transport.POST{})
	srv.AddTransport(transport.MultipartForm{})
	srv.SetQueryCache(lru.New(1000))
	srv.Use(extension.AutomaticPersistedQuery{
		Cache: lru.New(100),
	})

	if svcCtx.Config.Mode != service.ProMode {
		srv.Use(extension.Introspection{})
	} else {
		// srv.Use(extension.FixedComplexityLimit(15))
		srv.Use(extension.Introspection{})
	}
	// srv.AroundFields(func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) {
	// 	rc := graphql.GetFieldContext(ctx)
	// 	fmt.Println("Entered", rc.Object, rc.Field.Name)
	// 	res, err = next(ctx)
	// 	fmt.Println("Left", rc.Object, rc.Field.Name, "=>", res, err)
	// 	return res, err
	// })

	// wrap the query handler with middleware to inject dataloader
	// srv.Use(dataloader.Middleware(loader))
	return func(w http.ResponseWriter, r *http.Request) {
		nextCtx := dataloader.With(r.Context(), loader)
		r = r.WithContext(nextCtx)
		srv.ServeHTTP(w, r)
	}
}
